// #include <iostream>
// #include <opencv2/core.hpp>
// #include <opencv2/highgui.hpp>
// #include <opencv2/imgproc.hpp>
// #include <unordered_map>
// #include "yolov7.h"
// #include "BYTETracker.h"
// #include <queue>
// #include <vector>
// #include<fstream>
// #include <sstream>
// #include<string>
// #include <opencv2/imgproc/imgproc_c.h>
// #include <nlohmann/json.hpp>
// using json = nlohmann::json;
//
// #include <chrono>  // 引入计时器所需的头文件
//
//// 停车位状态结构体，包括是否有车和计时
// struct ParkingStatus {
//	bool hasCar;
//	std::chrono::time_point<std::chrono::system_clock> startTime;  // 开始计时的时间点
// };
//
//// 定义停车位状态的map
// std::map<int, ParkingStatus> ParkingJudgment_map;
//
// struct ParkingSpaceInfo
//{
//	int parkId;
//	int VehicleModel;
//	std::vector<cv::Point > CoordinateBox;
// };
//
// struct TrackBoxInfo
//{
//	//bool both_over = false;
//	bool begin_over = false;
//	bool end_over = false;
//	bool begin_frist = false;
//	bool end_frist = false;
// };
//
//
////读取json文件中标注框的信息
// std::map<int, ParkingSpaceInfo> ReadBBoxFromJson(std::string filename)
//{
//	std::ifstream f(filename);
//	std::ostringstream tmp;
//	tmp << f.rdbuf();
//	std::string str = tmp.str();
//
//	std::cout << str << std::endl;
//	json data = json::parse(str);
//
//	std::map<int, ParkingSpaceInfo> res;
//	std::map<std::string, int> car_dict = { {"car",0},{"truck",1},{"bus",2},{"all",3} };		//构建一个汽车字典
//
//	for (int i = 0; i < data["shapes"].size(); i++)
//	{
//		json points = data["shapes"][i]["points"];
//		json label = data["shapes"][i]["label"];
//
//		std::vector<cv::Point> tem;
//
//		for (int j = 0; j < points.size(); j++)
//		{
//			int x = points[j][0].template get<double>();
//			int y = points[j][1].template get<double>();
//			//std::cout << x << y << std::endl;
//			cv::Point point(x, y);
//			tem.push_back(point);
//		}
//		//res.push_back(tem);
//		std::string lab = label.get<std::string>();
//		//提取下划线后面的停车位编号
//		size_t underscorePos = lab.find("_");
//		std::string numberStr = lab.substr(underscorePos + 1);
//		int parkNum = std::stoi(numberStr);
//		//提取下划线前的车型
//		std::string VehicleModelStr = lab.substr(0, underscorePos);
//		//将字符串改为车型编号
//		int VehicleModelId = car_dict[VehicleModelStr];					// 查找对应的整数值
//
//		res[i].parkId = parkNum;
//		res[i].VehicleModel = VehicleModelId;
//		res[i].CoordinateBox = tem;
//	}
//	return res;
// }
//
//
////停车计时
// bool ParkingMeter(std::vector<BoxInfo> res, cv::Mat src, std::map<int, ParkingSpaceInfo> res_car, std::map<int, std::pair<int, std::chrono::steady_clock::time_point>>& ParkingJudgment_set,
//	std::map<int, int>& ParkingJudgment_frame)
//{
//	//将停车位的label记录下来作为判断是否有车的标志
//	for (auto it = res_car.begin(); it != res_car.end(); ++it)
//	{
//		int key = it->second.parkId;  // 获取停车位编号
//
//		auto iter_Pack = ParkingJudgment_set.find(key);
//		if (iter_Pack == ParkingJudgment_set.end())
//		{
//			ParkingJudgment_set.insert({ key, {0,std::chrono::steady_clock::now()} });
//		}
//		auto iter_frame = ParkingJudgment_frame.find(key);
//		if (iter_frame == ParkingJudgment_frame.end())
//		{
//			ParkingJudgment_frame.insert({ key,0 });
//		}
//	}
//
//	//判断中心点位置是否在停车位中，如果在则说明有车，需要遍历所有车位
//	for (auto it = res_car.begin(); it != res_car.end(); ++it)
//	{
//		int key = it->second.parkId;  // 获取停车位编号
//
//		// 获取到每个停车位的点坐标
//		std::vector<cv::Point> points = it->second.CoordinateBox;
//
//		bool isInside = false;
//
//		for (auto& i : res)
//		{
//			//判断车的中心点是否存在车位中，如果存在则说明停车位有车
//			//中心点
//			int center_x = i.x1 + (i.x2 - i.x1) / 2;
//			int center_y = i.y1 + ((i.y2 - i.y1) / 3 * 2);
//
//			circle(src, cv::Point(center_x, center_y), 1, cv::Scalar(255, 0, 0), 2);
//
//			//判断其是否在停车位中
//			cv::Rect targetRect(center_x, center_y, 1, 1); // 假设目标的位置由左上角坐标 (x, y) 和宽度高度 width 和 height 表示
//			isInside = cv::pointPolygonTest(points, cv::Point(targetRect.x, targetRect.y), false) >= 0
//				&& cv::pointPolygonTest(points, cv::Point(targetRect.x + targetRect.width, targetRect.y), false) >= 0
//				&& cv::pointPolygonTest(points, cv::Point(targetRect.x + targetRect.width, targetRect.y + targetRect.height), false) >= 0
//				&& cv::pointPolygonTest(points, cv::Point(targetRect.x, targetRect.y + targetRect.height), false) >= 0;
//
//			if (isInside)
//			{
//				//在停车框内则显示车目标
//				if(int(i.x1) >= 380 && int(i.y1) >= 680 && int(i.y1) <= 900) rectangle(src, cv::Point(i.x1, i.y1), cv::Point(i.x2, i.y2), cv::Scalar(0, 0, 255), 2);
//
//				auto iter_frame = ParkingJudgment_frame.find(key);
//				if (iter_frame != ParkingJudgment_frame.end())
//				{
//					if (iter_frame->second < 50)
//					{
//						iter_frame->second = iter_frame->second + 10;
//					}
//				}
//				continue;
//			}
//		}
//		if (isInside == false)
//		{
//			if (ParkingJudgment_frame[key] > -5)
//			{
//				ParkingJudgment_frame[key]--;
//			}
//		}
//	}
//
//	// 判断中心点位置是否在停车位中，如果在则说明有车，需要遍历所有车位
//	for (auto it = res_car.begin(); it != res_car.end(); ++it) {
//
//		int key = it->second.parkId;  // 获取停车位编号
//
//		auto iter_frame = ParkingJudgment_frame.find(key);
//		if (iter_frame != ParkingJudgment_frame.end())
//		{
//			if (iter_frame->second < 0)
//			{
//				ParkingJudgment_map[key].hasCar = false;  // 没有车
//				ParkingJudgment_map[key].startTime = std::chrono::time_point<std::chrono::system_clock>();  // 清除计时
//			}
//			else if (iter_frame->second > 20) {
//				ParkingJudgment_map[key].hasCar = true;  // 有车
//				if (!ParkingJudgment_map[key].startTime.time_since_epoch().count()) {
//					ParkingJudgment_map[key].startTime = std::chrono::system_clock::now();  // 开始计时
//				}
//			}
//		}
//	}
//
//	//遍历所有的停车车位,超时进行报警
//	for (auto it = res_car.begin(); it != res_car.end(); ++it)
//	{
//		int key = it->second.parkId;  // 获取int值
//
//		if (ParkingJudgment_map[key].hasCar) {
//			// 在停车框的右上角显示红色文字
//			// 计算文本位置
//			// 遍历vector中的点坐标
//			std::vector<cv::Point> points = it->second.CoordinateBox;
//			cv::polylines(src, points, true, cv::Scalar(255, 0, 0), 2); // 最后两个参数分别表示是否闭合边框和线段的粗细，Scalar为BGR颜色值
//
//			// 计算经过的时间
//			auto currentTime = std::chrono::system_clock::now();
//			auto diff = std::chrono::duration_cast<std::chrono::seconds>(currentTime - ParkingJudgment_map[key].startTime);
//			int hours = static_cast<int>(diff.count() / 3600);
//			int minutes = static_cast<int>((diff.count() % 3600) / 60);
//			int seconds = static_cast<int>(diff.count() % 60);
//			std::stringstream ss;
//
//			ss << std::setfill('0') << std::setw(1) << hours << "h"
//				<< std::setw(2) << minutes << "m"
//				<< std::setw(2) << seconds << "s";
//			std::string timeString = ss.str();
//
//			//计算文本位置
//			cv::Rect boundingRect = cv::boundingRect(points);
//			cv::Point2f textPosition(boundingRect.x, boundingRect.y + boundingRect.height * 2 / 3);
//			if (!(int(textPosition.x) >= 383 && int(textPosition.y) >= 820 && int(textPosition.y) <= 900)) continue;
//			//判断小车停留时间
//			if (it->second.VehicleModel == 0)
//				//if (true)
//			{
//				if ((seconds >= 30 || minutes >= 1))
//				{
//					//报警在图像上显示计时结果
//					cv::rectangle(src, cv::Point(textPosition.x, textPosition.y), cv::Point(textPosition.x + round(20 * 6), textPosition.y + round(2 * 15)), cv::Scalar(0, 0, 255), CV_FILLED);
//					putText(src, timeString, cv::Point(textPosition.x, textPosition.y + round(2 * 10)), cv::FONT_HERSHEY_COMPLEX_SMALL, 1, cv::Scalar(255, 255, 255), 2);  // 蓝色文字
//					if (ParkingJudgment_set[key].first == 0)
//					{
//						ParkingJudgment_set[key].first++;
//					}
//				}
//				else
//				{
//					//显示时间框
//					cv::rectangle(src, cv::Point(textPosition.x, textPosition.y), cv::Point(textPosition.x + round(20 * 6), textPosition.y + round(2 * 15)), cv::Scalar(255, 0, 0), CV_FILLED);
//					putText(src, timeString, cv::Point(textPosition.x, textPosition.y + round(2 * 10)), cv::FONT_HERSHEY_COMPLEX_SMALL, 1, cv::Scalar(255, 255, 255), 2);  // 蓝色文字
//				}
//			}
//			//判断货车或危化品车或大客车停留时间
//			if (it->second.VehicleModel == 1 || it->second.VehicleModel == 2)
//				//if (true)
//			{
//				if (hours >= 2 && ParkingJudgment_set[key].first == 0)
//				{
//					//报警在图像上显示计时结果
//					cv::rectangle(src, cv::Point(textPosition.x, textPosition.y), cv::Point(textPosition.x + round(20 * 6), textPosition.y + round(2 * 15)), cv::Scalar(0, 0, 255), CV_FILLED);
//					putText(src, timeString, cv::Point(textPosition.x, textPosition.y + round(2 * 10)), cv::FONT_HERSHEY_COMPLEX_SMALL, 1, cv::Scalar(255, 255, 255), 2);  // 蓝色文字
//					ParkingJudgment_set[key].first++;
//				}
//				else
//				{
//					//显示时间框
//					cv::rectangle(src, cv::Point(textPosition.x, textPosition.y), cv::Point(textPosition.x + round(20 * 6), textPosition.y + round(2 * 15)), cv::Scalar(255, 0, 0), CV_FILLED);
//					putText(src, timeString, cv::Point(textPosition.x, textPosition.y + round(2 * 10)), cv::FONT_HERSHEY_COMPLEX_SMALL, 1, cv::Scalar(255, 255, 255), 2);  // 蓝色文字
//					ParkingJudgment_set[key].first = 0;
//				}
//			}
//		}
//	}
//
//	//报警触发
//	for (auto& i : ParkingJudgment_set)
//	{
//		//触发报警
//		if (i.second.first == 1)
//		{
//			i.second.second = std::chrono::steady_clock::now();
//			i.second.first++;
//			//直接返回发送消息
//			return true;
//
//		}
//		//报警间隔继续报警
//		if (i.second.first == 2)
//		{
//			// 计算已经过去的时间
//			std::chrono::steady_clock::time_point currentTime = std::chrono::steady_clock::now();
//			std::chrono::duration<double> elapsedSeconds = currentTime - i.second.second;
//
//			//间隔10分钟置0
//			if (elapsedSeconds.count() >= 30)
//			{
//				i.second.first = 0;
//			}
//		}
//	}
//	return false;
// }
//
//
//
// int main()
//{
//	cv::VideoCapture cap("videos/3_cam2_11_28_rotate.mp4");
//
//	std::string modelname = "models/best(5).onnx";
//	Net_config config = { 0.5,0.5,modelname };
//	YOLOV7 yolov7_(config, "YOLOV7");
//	byte_track::BYTETracker* tracker = new byte_track::BYTETracker(15, 35);
//	cv::Mat src, dst;
//	cap >> src;
//
//	cv::VideoWriter writer;
//	writer.open("test_copy.avi", cv::VideoWriter::fourcc('X', 'V', 'I', 'D'), 15, cv::Size(src.cols, src.rows));
//
//	std::string filename = "D:/data/myCodeCPP/yoloCpp/yolo/json/cichengxi/cam2.json";
//
//	/*******************变量集合***************************/
//	std::map<int, ParkingSpaceInfo> res_car;
//
//
//	//读取每个停车位的坐标
//	res_car = ReadBBoxFromJson(filename);
//
//	std::map<int, std::pair<int, std::chrono::steady_clock::time_point>> ParkingJudgment_set;		         //停车判断报警标志 0为正常，1为报警
//	std::map<int, int> ParkingJudgment_frame;																 //停车计数
//
//
//	while (!src.empty())
//	{
//		//做yolov7检测
//		std::vector<BoxInfo> res = yolov7_.detect(src);
//		std::vector<byte_track::Object> obj_vec;
//
//
//		//停车计时
//		bool sendFlag = ParkingMeter(res, src, res_car, ParkingJudgment_set, ParkingJudgment_frame);
//		//发送数据
//
//		std::vector<byte_track::Object> obj_vec1;
//
//
//
//		cv::Mat showImg;
//		cv::resize(src, showImg, cv::Size(512 * 3, 384 * 3));
//		cv::imshow("src", showImg);
//		cv::waitKey(1);
//
//		writer.write(src);
//		cap >> src;
//	}
//	cap.release();
//	writer.release();
//	return 1;
// }
//
